'
' *  Authors:  Benton Stark
' * 
' *  Copyright (c) 2007-2012 Starksoft, LLC (http://www.starksoft.com) 
' *
' * Permission is hereby granted, free of charge, to any person obtaining a copy
' * of this software and associated documentation files (the "Software"), to deal
' * in the Software without restriction, including without limitation the rights
' * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
' * copies of the Software, and to permit persons to whom the Software is
' * furnished to do so, subject to the following conditions:
' * 
' * The above copyright notice and this permission notice shall be included in
' * all copies or substantial portions of the Software.
' * 
' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
' * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
' * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
' * THE SOFTWARE.
' * 
' 


Imports System.Collections.Generic
Imports System.Text
Imports System.Net.Sockets

Namespace Proxy
    ''' <summary>
    ''' The type of proxy.
    ''' </summary>
    Public Enum ProxyType
        ''' <summary>
        ''' No Proxy specified.  Note this option will cause an exception to be thrown if used to create a proxy object by the factory.
        ''' </summary>
        None
        ''' <summary>
        ''' HTTP Proxy
        ''' </summary>
        Http
        ''' <summary>
        ''' SOCKS v4 Proxy
        ''' </summary>
        Socks4
        ''' <summary>
        ''' SOCKS v4a Proxy
        ''' </summary>
        Socks4a
        ''' <summary>
        ''' SOCKS v5 Proxy
        ''' </summary>
        Socks5
    End Enum

    ''' <summary>
    ''' Factory class for creating new proxy client objects.
    ''' </summary>
    ''' <remarks>
    ''' <code>
    ''' // create an instance of the client proxy factory
    ''' ProxyClientFactory factory = new ProxyClientFactory();
    '''        
    ''' // use the proxy client factory to generically specify the type of proxy to create
    ''' // the proxy factory method CreateProxyClient return an IProxyClient object
    ''' IProxyClient proxy = factory.CreateProxyClient(ProxyType.Http, "localhost", 6588);
    '''
    ''' // create a connection through the proxy to www.starksoft.com over port 80
    ''' System.Net.Sockets.TcpClient tcpClient = proxy.CreateConnection("www.starksoft.com", 80);
    ''' </code>
    ''' </remarks>
    Public Class ProxyClientFactory

        ''' <summary>
        ''' Factory method for creating new proxy client objects.
        ''' </summary>
        ''' <param name="type">The type of proxy client to create.</param>
        ''' <return>Proxy client object.</return>
        Public Function CreateProxyClient(type As ProxyType) As IProxyClient
            If type = ProxyType.None Then
                Throw New ArgumentOutOfRangeException("type")
            End If

            Select Case type
                Case ProxyType.Http
                    Return New HttpProxyClient()
                Case ProxyType.Socks4
                    Return New Socks4ProxyClient()
                Case ProxyType.Socks4a
                    Return New Socks4aProxyClient()
                Case ProxyType.Socks5
                    Return New Socks5ProxyClient()
                Case Else
                    Throw New ProxyException([String].Format("Unknown proxy type {0}.", type.ToString()))
            End Select
        End Function

        ''' <summary>
        ''' Factory method for creating new proxy client objects using an existing TcpClient connection object.
        ''' </summary>
        ''' <param name="type">The type of proxy client to create.</param>
        ''' <param name="tcpClient">Open TcpClient object.</param>
        ''' <return>Proxy client object.</return>
        Public Function CreateProxyClient(type As ProxyType, tcpClient As TcpClient) As IProxyClient
            If type = ProxyType.None Then
                Throw New ArgumentOutOfRangeException("type")
            End If

            Select Case type
                Case ProxyType.Http
                    Return New HttpProxyClient(tcpClient)
                Case ProxyType.Socks4
                    Return New Socks4ProxyClient(tcpClient)
                Case ProxyType.Socks4a
                    Return New Socks4aProxyClient(tcpClient)
                Case ProxyType.Socks5
                    Return New Socks5ProxyClient(tcpClient)
                Case Else
                    Throw New ProxyException([String].Format("Unknown proxy type {0}.", type.ToString()))
            End Select
        End Function

        ''' <summary>
        ''' Factory method for creating new proxy client objects.  
        ''' </summary>
        ''' <param name="type">The type of proxy client to create.</param>
        ''' <param name="proxyHost">The proxy host or IP address.</param>
        ''' <param name="proxyPort">The proxy port number.</param>
        ''' <return>Proxy client object.</return>
        Public Function CreateProxyClient(type As ProxyType, proxyHost As String, proxyPort As Integer) As IProxyClient
            If type = ProxyType.None Then
                Throw New ArgumentOutOfRangeException("type")
            End If

            Select Case type
                Case ProxyType.Http
                    Return New HttpProxyClient(proxyHost, proxyPort)
                Case ProxyType.Socks4
                    Return New Socks4ProxyClient(proxyHost, proxyPort)
                Case ProxyType.Socks4a
                    Return New Socks4aProxyClient(proxyHost, proxyPort)
                Case ProxyType.Socks5
                    Return New Socks5ProxyClient(proxyHost, proxyPort)
                Case Else
                    Throw New ProxyException([String].Format("Unknown proxy type {0}.", type.ToString()))
            End Select
        End Function

        ''' <summary>
        ''' Factory method for creating new proxy client objects.  
        ''' </summary>
        ''' <param name="type">The type of proxy client to create.</param>
        ''' <param name="proxyHost">The proxy host or IP address.</param>
        ''' <param name="proxyPort">The proxy port number.</param>
        ''' <param name="proxyUsername">The proxy username.  This parameter is only used by Http, Socks4 and Socks5 proxy objects.</param>
        ''' <param name="proxyPassword">The proxy user password.  This parameter is only used Http, Socks5 proxy objects.</param>
        ''' <return>Proxy client object.</return>
        Public Function CreateProxyClient(type As ProxyType, proxyHost As String, proxyPort As Integer, proxyUsername As String, proxyPassword As String) As IProxyClient
            If type = ProxyType.None Then
                Throw New ArgumentOutOfRangeException("type")
            End If

            Select Case type
                Case ProxyType.Http
                    Return New HttpProxyClient(proxyHost, proxyPort, proxyUsername, proxyPassword)
                Case ProxyType.Socks4
                    Return New Socks4ProxyClient(proxyHost, proxyPort, proxyUsername)
                Case ProxyType.Socks4a
                    Return New Socks4aProxyClient(proxyHost, proxyPort, proxyUsername)
                Case ProxyType.Socks5
                    Return New Socks5ProxyClient(proxyHost, proxyPort, proxyUsername, proxyPassword)
                Case Else
                    Throw New ProxyException([String].Format("Unknown proxy type {0}.", type.ToString()))
            End Select
        End Function

        ''' <summary>
        ''' Factory method for creating new proxy client objects.  
        ''' </summary>
        ''' <param name="type">The type of proxy client to create.</param>
        ''' <param name="tcpClient">Open TcpClient object.</param>
        ''' <param name="proxyHost">The proxy host or IP address.</param>
        ''' <param name="proxyPort">The proxy port number.</param>
        ''' <param name="proxyUsername">The proxy username.  This parameter is only used by Http, Socks4 and Socks5 proxy objects.</param>
        ''' <param name="proxyPassword">The proxy user password.  This parameter is only used Http, Socks5 proxy objects.</param>
        ''' <return>Proxy client object.</return>
        Public Function CreateProxyClient(type As ProxyType, tcpClient As TcpClient, proxyHost As String, proxyPort As Integer, proxyUsername As String, proxyPassword As String) As IProxyClient
            Dim c As IProxyClient = CreateProxyClient(type, proxyHost, proxyPort, proxyUsername, proxyPassword)
            c.TcpClient = tcpClient
            Return c
        End Function


    End Class



End Namespace
